package matrici;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

/**
 * 
 * @author Luca
 */
public class MatriceInversa extends JPanel implements ActionListener, KeyListener {

    static JFrame f;
    JPanel intro, fin, pA, pI, pGo;
    JTextField dimMatrice;
    JTextField[][] mA, mI;
    JButton go, jordan;
    int dim = 0, i = 0;

    /**
     * 
     */
    public MatriceInversa() {
        intro = new JPanel();
        this.add(intro);
        intro.add(new JLabel("Dimensione matrice"));
        dimMatrice = new JTextField();
        dimMatrice.setPreferredSize(new Dimension(40, 20));
        intro.add(dimMatrice);
        dimMatrice.addKeyListener(this);
    }

    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
        MatriceInversa m = new MatriceInversa();
        f = new JFrame();
        f.setVisible(true);
        f.setTitle("Matrice inversa");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocation(200, 200);
        f.add(m);

        f.pack();

        //System.out.println(op("--3","+","2"));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(go)) {
            scalina();
        }
        if (e.getSource().equals(jordan)) {
            jordan();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getSource().equals(dimMatrice)) {
            char typed = e.getKeyChar();
            if (typed != '0' && typed != '1' && typed != '2' && typed != '3'
                    && typed != '4' && typed != '5' && typed != '6' && typed != '7'
                    && typed != '8' && typed != '9' && typed != '\n' && typed != '\b') {
                String temp = dimMatrice.getText();
                temp = temp.substring(0, temp.length() - 1);
                dimMatrice.setText(temp);
            }
            if (e.getKeyChar() == '\n') {
                try {
                    dim = new Integer(dimMatrice.getText());
                } catch (NumberFormatException ne) {
                    dim = 0;
                }
                if (dim > 0) {
                    inserisci();
                }
            }
        }
    }

    void inserisci() {
        intro.setVisible(false);

        fin = new JPanel();
        pA = new JPanel();
        pI = new JPanel();
        pGo = new JPanel();

        fin.setLayout(new BorderLayout());

        pA.setLayout(new GridLayout(dim, dim));
        mA = new JTextField[dim][dim];
        Random generator = new Random();
        for (int i = 0; i < dim; i++) {
            for (int j = 0; j < dim; j++) {
                mA[i][j] = new JTextField();
                mA[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                mA[i][j].setPreferredSize(new Dimension(40, 20));
                mA[i][j].setText(new Integer(generator.nextInt(9) + 1).toString());
                pA.add(mA[i][j]);
            }
        }

        pGo.setLayout(new GridLayout(2, 1));

        go = new JButton("Scalina");
        go.addActionListener(this);

        jordan = new JButton("Jordan");
        jordan.addActionListener(this);
        jordan.setEnabled(false);

        pGo.add(go);
        pGo.add(jordan);

        pI.setLayout(new GridLayout(dim, dim));
        mI = new JTextField[dim][dim];
        for (int i = 0; i < dim; i++) {
            for (int j = 0; j < dim; j++) {
                mI[i][j] = new JTextField("0");
                mI[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                mI[i][j].setPreferredSize(new Dimension(40, 20));
                mI[i][j].setEditable(false);
                if (i == j) {
                    mI[i][j].setText("1");
                }
                pI.add(mI[i][j]);
            }
        }

        fin.add(pA, BorderLayout.WEST);
        fin.add(pGo, BorderLayout.CENTER);
        fin.add(pI, BorderLayout.EAST);

        this.add(fin);
        f.pack();
    }

    static String op(String a, String s, String b) {

        int numeratoreA, denominatoreA, numeratoreB, denominatoreB;
        int numeratoreRisultato = 0, denominatoreRisultato = 0, max = 0, temp;
        boolean flag = false;

        if (a.contains("--")) {
            a = a.replace("--", "");
        }
        if (b.contains("--")) {
            b = b.replace("--", "");
        }

        String[] A = a.split("/");
        if (A.length == 1) {
            numeratoreA = new Integer(A[0]);
            denominatoreA = 1;
        } else {
            numeratoreA = new Integer(A[0]);
            denominatoreA = new Integer(A[1]);
        }

        String[] B = b.split("/");
        if (B.length == 1) {
            numeratoreB = new Integer(B[0]);
            denominatoreB = 1;
        } else {
            numeratoreB = new Integer(B[0]);
            denominatoreB = new Integer(B[1]);
        }

        if (s.equals("+")) {
            denominatoreRisultato = denominatoreA * denominatoreB;
            numeratoreRisultato = (denominatoreRisultato * numeratoreA / denominatoreA) + (denominatoreRisultato * numeratoreB / denominatoreB);
        }

        if (s.equals("-")) {
            denominatoreRisultato = denominatoreA * denominatoreB;
            numeratoreRisultato = (denominatoreRisultato * numeratoreA / denominatoreA) - (denominatoreRisultato * numeratoreB / denominatoreB);
        }

        if (s.equals("*")) {
            denominatoreRisultato = denominatoreA * denominatoreB;
            numeratoreRisultato = numeratoreA * numeratoreB;
        }

        if (s.equals(":")) {
            denominatoreRisultato = denominatoreA * numeratoreB;
            numeratoreRisultato = numeratoreA * denominatoreB;
        }


        do {
            if (denominatoreRisultato < 0 || numeratoreRisultato < 0) {
                if (denominatoreRisultato < 0 && numeratoreRisultato < 0) {
                    denominatoreRisultato *= -1;
                    numeratoreRisultato *= -1;
                    if (denominatoreRisultato > numeratoreRisultato) {
                        max = denominatoreRisultato;
                    } else {
                        max = numeratoreRisultato;
                    }
                } else {
                    if (denominatoreRisultato < 0) {
                        temp = denominatoreRisultato * -1;
                        if (temp > numeratoreRisultato) {
                            max = temp;
                        } else {
                            max = numeratoreRisultato;
                        }
                    }
                    if (numeratoreRisultato < 0) {
                        temp = numeratoreRisultato * -1;
                        if (temp > denominatoreRisultato) {
                            max = temp;
                        } else {
                            max = denominatoreRisultato;
                        }
                    }
                }
            } else {
                if (denominatoreRisultato > numeratoreRisultato) {
                    max = denominatoreRisultato;
                } else {
                    max = numeratoreRisultato;
                }
            }

            flag = false;

            for (int i = max; (i > 1) && (flag == false); i--) {
                flag = false;
                if ((denominatoreRisultato % i == 0) && (numeratoreRisultato % i == 0)) {
                    denominatoreRisultato /= i;
                    numeratoreRisultato /= i;
                    flag = true;
                }
            }
        } while (flag == true);

        String res = "";

        if (denominatoreRisultato == 1) {
            res += numeratoreRisultato;
        } else {
            if (numeratoreRisultato == 0) {
                res += "0";
            } else {
                res += numeratoreRisultato + "/" + denominatoreRisultato;
            }
        }

        if (denominatoreRisultato == -1) {
            res = "-" + numeratoreRisultato;
        }

        if (res.contains("-")) {
            res = "-" + res.replace("-", "");
        }

        //System.out.println(res);

        return res;
    }

    void scalina2() {
        for (int i = 0; i < dim - 1; i++) {
            for (int j = i + 1; j < dim; j++) {
                String temp = mA[j][i].getText();
                for (int k = i; k < dim; k++) {
                    mA[j][k].setText(op(op(op("-" + mA[i][i].getText(), ":", temp), "*", mA[j][k].getText()), "+", mA[i][k].getText()));
                }
            }
        }
    }

    void scalina() {
//        for (int i = 0; i < dim; i++) {
        String temp = mA[i][i].getText();
        for (int k = i; k < dim; k++) {
            mA[i][k].setText(op(mA[i][k].getText(), ":", temp));
        }
        for (int k = 0; k < dim; k++) {
            mI[i][k].setText(op(mI[i][k].getText(), ":", temp));
        }
        if (i < dim - 1) {
            for (int j = i + 1; j < dim; j++) {
                temp = mA[j][i].getText();
                for (int k = i; k < dim; k++) {
                    mA[j][k].setText(op(op("-" + temp, "*", mA[i][k].getText()), "+", mA[j][k].getText()));
                }
                for (int k = 0; k < dim; k++) {
                    mI[j][k].setText(op(op("-" + temp, "*", mI[i][k].getText()), "+", mI[j][k].getText()));
                }
            }
        }
        i++;

        if (i == dim) {
            jordan.setEnabled(true);
            go.setEnabled(false);
            i = dim - 2;
        }
//        }
    }

    void jordan() {

        String temp;
        if (i >= 0) {
            for (int j = i; j >= 0; j--) {
                temp = mA[j][i + 1].getText();
                for (int k = 0; k < dim; k++) {
                    mA[j][k].setText(op(op("-" + temp, "*", mA[i + 1][k].getText()), "+", mA[j][k].getText()));
                    mI[j][k].setText(op(op("-" + temp, "*", mI[i + 1][k].getText()), "+", mI[j][k].getText()));
                }
            }
            i--;
        } else {
            jordan.setEnabled(false);
        }
    }
}